'''
Created on 17 nov 2010

@author: Xakt
'''

import math
import pickle
import random
import copy
import settings
import os
import sys
import time
import pprint

class AgentBrain():
    
    def __init__(self):
        self.previousState = ''
        self.previousAction = ''
        self.DEFAULTVALUES = {'goToControlpoint':15, 'shootEnemy':15, 'getAmmo':15, 'flee':15, 'turnToEnemy':15, 'defendControlpoint':15}
        self.extraReward = 0
        self.stateActionDict = {}        
        self.timestep = 0
        self.waypoints = [[510, 480], [490, 480], [510, 520], [490, 520], [480, 510], [480, 490], [520, 510], [520, 490]]
        self.previousStepControlpoints = {}
        
        # Needed for plotting progress
        self.oldStateActionDict = {}
        self.differencesDict = {}
        self.nrStatesDict = {}
        
        # Rewards
        self.captureReward = 100    
        self.shootingWhileNoEnemy = -100
        self.fleeNoEnemy = -100
        self.noAmmo = -100
        self.enoughAmmo = -100
        self.turnWhileNoEnemy = -100
        self.shootingWhileNoAmmo = -100
        self.shootingReward = 100
        self.outOfRange = -100
        self.turnWhileNoAmmo = -100
        self.respawnReward = -100
        
        self.EXPLORATIONFACTOR = 0.0
        
        # timing
        self.start_time = time.clock()

        
    def action(self, observation):
        if observation['id'] == 1:
            return self.spawnKiller(observation)
        if self.timestep == 0:
            self.stateActionDict = self.openDict(observation['id'],observation['team'])
            self.oldStateActionDict = copy.deepcopy(self.openDict(observation['id'],observation['team']))
    
        self.timestep += 1
        
        if self.timestep % 100 == 0:

            if observation['id'] == 2:                
                print "\n SAVING DICTIONARY\n"
                print observation['team']
                print "timestep: ",
                print self.timestep
                self.compareStateDicts(self.oldStateActionDict,self.stateActionDict,self.timestep)
                for key in sorted(self.differencesDict):
                    print str(key) + ": ",
                    print str(self.differencesDict[key]) + " ",
                print "\n"
                for key in sorted(self.nrStatesDict):
                    print str(key) + ": ",
                    print str(self.nrStatesDict[key]) + " ",
                print "\n"
                time_busy = time.clock() - self.start_time
                print "Total time: ",
                print time_busy
                print "Time per step: ",
                print time_busy/self.timestep
                print "\n\n"
            self.saveDict(self.stateActionDict,observation['id'],observation['team'])
            
        self.checkForControlpointChanges(observation)
            
        state = self.toState(observation)
        
        if not state in self.stateActionDict:
            self.stateActionDict[state] = copy.deepcopy(self.DEFAULTVALUES)
        
        self.stateActionDict = self.update(self.stateActionDict, observation, state)
        
        # determine role
        role = self.determineRole(observation)
        
        # do something with role, not yet implemented
        
        if role == "attacker":
            action = self.selectActionAttacker(self.stateActionDict[state], observation)
        elif role == "defender":
#            print 'defender role assigned'
            action = self.selectActionDefender(self.stateActionDict[state], observation)
        self.previousState = state
        
        return action
    
    def determineRole(self, observation):
        # assigns a role to an agent dynamically
        # 1 = attacker
        # 2 = defender
        uncontrolledControlpoints = False
        for controlpoint in observation['controlpoints']:
            if controlpoint['team'] != observation['team']:
                uncontrolledControlpoints = True
        if not uncontrolledControlpoints:
            return "defender"
        
        for controlpoint in observation['controlpoints']:
            distanceToControlpoint = self.getDistance(observation['location'], controlpoint['location']) 
            if  distanceToControlpoint < settings.SIGHT:
                if controlpoint['team'] == observation['team']:
                    isClosest = True
                    for agent in observation['agents']:
                        if agent != self.isEnemy(agent, observation['team']):
                            if self.getDistance(agent['location'], controlpoint['location']) < distanceToControlpoint:
                                isClosest = False
                    if isClosest:
                        return "defender"
        return "attacker"
                
        
    def turnToEnemy(self, observation):
        if observation['ammo'] == 0:
            self.extraReward += self.turnWhileNoAmmo
            return {
                    'turn': 0,
                    'speed' :0,
                    'shoot': False
                    }
        agents = observation['agents']
        enemiesInSight = []
        for agent in agents:
            if agent['team'] != observation['team']:
                angle = self.angleWithAgent(agent['location'], observation['location'], observation['direction'])
                if angle >= 2* -settings.MAX_TURN and angle <= 2* settings.MAX_TURN:
                    if settings.MAX_SHOT_DISTANCE < self.getDistance(observation['location'],agent['location']) < settings.SIGHT:
                        enemiesInSight.append(agent)
        if enemiesInSight == []:
#            print "giving -100 reward for turning when there's no enemy"
            self.extraReward += self.turnWhileNoEnemy            
            return {
                    'turn': 0,
                    'speed' :0,
                    'shoot': False
                    }
        smallest_angle = settings.MAX_TURN*3
        for enemy in enemiesInSight:
            angle = self.angleWithAgent(enemy['location'],observation['location'], observation['direction'])
            if abs(angle) < abs(smallest_angle):
                smallest_angle = angle
        action = {
                   'turn': math.radians(angle),
                   'speed': settings.MIN_SPEED,
                   'shoot': False
                  }
        return action
    
    def compareStateDicts(self,oldStateActionDict,stateActionDict,timestep):
            difference = 0
            # Compare values of old states
            for state, actionDict in oldStateActionDict.iteritems():
                for action, value in actionDict.iteritems():                    
                    difference += math.fabs(value - stateActionDict[state][action])
            # Adjust difference according to number of states and actions            
            if len(oldStateActionDict) > 0 :
                difference = (difference/len(oldStateActionDict))/len(self.DEFAULTVALUES)
            self.differencesDict[timestep] = difference
            self.nrStatesDict[timestep] = len(stateActionDict)
                
            self.oldStateActionDict = copy.deepcopy(stateActionDict)

        
    def checkForControlpointChanges(self,observation):
        # Function checks for each controlpoint if it has changed owner, if your team captured
        # one then give reward to the agent who is most likely to have captured it
        # First check to skip this part when nothing has changed
        if self.previousStepControlpoints != observation['controlpoints']:
            for i in range(0,len(self.previousStepControlpoints)):
                if  observation['controlpoints'][i]['team'] != self.previousStepControlpoints[i]['team']:
                    if observation['controlpoints'][i]['team'] == observation['team']:
                        # If you are really close to the captured point, you must be the one who took it, so you
                        # get extra reward :) This is an approximation, so sometime multiple agents will get a reward
                        if self.getDistance(observation['location'], observation['controlpoints'][i]['location']) < 20:
                            self.extraReward += self.captureReward                                   
        self.previousStepControlpoints = observation['controlpoints']

    
    def flee(self,observation):
        agents = observation['agents']
        sumAgentLoc = (0,0)
        location = observation['location']
        
        enemyAgents = []
        for agent in agents:
            if self.isEnemy(agent, observation['team']):
                angle = self.angleWithAgent(observation['location'], agent['location'], agent['direction'])
                if angle <= -settings.MAX_TURN or angle >= settings.MAX_TURN:
                    continue
                enemyAgents.append(agent)
        
        if enemyAgents == []:
            self.extraReward += self.fleeNoEnemy
            return {
                    'turn': 0,
                    'speed' :0,
                    'shoot': False
                    }
        
        for agent in enemyAgents:
            relLoc = (agent['location'][0]-location[0],agent['location'][1]-location[1])
            sumAgentLoc = (sumAgentLoc[0]+relLoc[0],sumAgentLoc[1]+relLoc[1])
        sumAgentLoc = (-sumAgentLoc[0]+location[0],-sumAgentLoc[1]+location[1])
            
#        print 'agents',agents
#        print 'team',observation['team']
#        print 'loc',location
#        print 'dir',observation['direction']
#        print 'sumloc',sumAgentLoc
        
        action = {
                   'turn': math.radians(self.angleWithAgent(sumAgentLoc, observation['location'], observation['direction'])),
                   'speed': 50,
                   'shoot': False
                  }
        
#        print 'action',action
        
        return action
    
    def selectActionAttacker(self, actionValues, observation):
        
        toDo = ''
        if random.random() < self.EXPLORATIONFACTOR:
            # explore
            actions = actionValues.keys()
            actions.remove('defendControlpoint')
            dictSize = len(actions)
            toDo = actions[int(math.floor(dictSize*random.random()))]
        else:
            # greedy
            toDo = ''
            maxValue = -9999999
            for action2, value in actionValues.iteritems():
                if value > maxValue and action2 != 'defendControlpoint':
                    maxValue = value
                    toDo = action2
#        print toDo
        self.previousAction = toDo
        if toDo == 'goToControlpoint':
            action = self.goToControlpoint(observation)
        elif toDo == 'shootEnemy':
            action = self.fireAtEnemy(observation)
        elif toDo == 'getAmmo':
            action = self.getAmmo(observation)
        elif toDo == 'flee':
            action = self.flee(observation)
        elif toDo == 'turnToEnemy':
            action = self.turnToEnemy(observation)
        elif toDo == 'defendControlpoint':
            print 'this should never happen (attacker)'
        return action
    
    def selectActionDefender(self, actionValues, observation):
        
        toDo = ''
        if random.random() < self.EXPLORATIONFACTOR:
            # explore
            
            actions = actionValues.keys()
            actions.remove('goToControlpoint')
            dictSize = len(actions)
            toDo = actions[int(math.floor(dictSize*random.random()))]
        else:
            # greedy
            toDo = ''
            maxValue = -9999999
            for action2, value in actionValues.iteritems():
                if value > maxValue and action2 != 'goToControlpoint':
                    maxValue = value
                    toDo = action2
#        print toDo
        self.previousAction = toDo
        if toDo == 'defendControlpoint':
            action = self.defendControlpoint(observation)
        elif toDo == 'shootEnemy':
            action = self.fireAtEnemy(observation)
        elif toDo == 'getAmmo':
            action = self.getAmmo(observation)
        elif toDo == 'flee':
            action = self.flee(observation)
        elif toDo == 'turnToEnemy':
            action = self.turnToEnemy(observation)
        elif toDo == 'goToControlpoint':
            print 'this should never happen!'
        return action
    
    def defendControlpoint(self, observation):
        smallDistance = 5
        closestControlpoint = []
        distanceToClosest = sys.maxint
        for controlpoint in observation['controlpoints']:
            distanceToControlpoint = self.getDistance(controlpoint['location'], observation['location']) 
            if distanceToControlpoint < distanceToClosest:
                closestControlpoint = controlpoint
                distanceToClosest = distanceToControlpoint
        if distanceToClosest > smallDistance:
            action = self.goToPoint(observation, closestControlpoint['location'], distanceToClosest)
        else:
            # nice hardcoded view points :<
            if closestControlpoint['location'] == (500,500):
                if observation['team'] == "Red":
                    action = self.goToPoint(observation, (40, 40), 0)
                else:
                    action = self.goToPoint(observation, (960, 960), 0)
            else:
                action = self.goToPoint(observation, (500, 500), 0)
        return action
    
    def getAmmo(self,observation, spawnKiller = False):
        ammopacks = observation['ammopacks']
        if ammopacks == []:
            self.extraReward += self.noAmmo
            return {
                    'turn': 0,
                    'speed': 0,
                    'shoot': False                  
                    }
        if observation['ammo'] > 5 and not spawnKiller:
            self.extraReward += self.enoughAmmo
            return {
                    'turn': 0,
                    'speed': 0,
                    'shoot': False                  
                    }
        closest_distance = settings.SIGHT*2
        toPickup = []
        for ammopack in ammopacks:
            distance = self.getDistance(observation['location'], ammopack['location'])
            if distance < closest_distance:
                closest_distance = distance
                toPickup = ammopack['location']
        action = self.goToPoint(observation, toPickup, closest_distance)
        
#        angle = self.angleWithAgent(toPickup, observation['location'], observation['direction'])
#        if not self.obstacleCheck(observation['location'], observation['walls'], toPickup) == []:
#            waypoint = self.getNearestWaypoint(observation['location'])
#            angle = self.angleWithAgent(waypoint, observation['location'], observation['direction'])
#        if angle >= -60 and angle <= 60:
#            speed = closest_distance
#        else:
#            speed = 0
#        action = {
#                   'turn': math.radians(angle),
#                   'speed': speed,
#                   'shoot': False
#                  }
        return action
    
    def getDistance(self, fromLoc, toLoc):
        distance = math.sqrt(math.pow((toLoc[0] - fromLoc[0]),2) + math.pow((toLoc[1] - fromLoc[1]),2))
        return distance
            
    def fireAtEnemy(self,observation):
        agents = observation['agents']
        enemiesInSight = []
        for agent in agents:
            if agent['team'] != observation['team']:
                angle = self.angleWithAgent(agent['location'], observation['location'], observation['direction'])
                if angle >= -60 and angle <= 60:
                    enemiesInSight.append(agent)
        if enemiesInSight == []:
#            print "giving -100 reward for shooting when theres no enemy"
            self.extraReward += self.shootingWhileNoEnemy            
            return {
                    'turn': 0,
                    'speed' :0,
                    'shoot': False
                    }
        if observation['ammo'] == 0:
#            print "giving -100 reward for shooting when theres no ammo"
            self.extraReward += self.shootingWhileNoAmmo
            return {
                    'turn': 0,
                    'speed' :0,
                    'shoot': False
                    }            

        closest_distance = settings.SIGHT*2
        toAttack = []
        for enemy in enemiesInSight:
            distance = self.getDistance(observation['location'],enemy['location'])
            if distance < closest_distance:
                closest_distance = distance
                toAttack = enemy
        # Check if there is a wall between target and agent
        if not self.obstacleCheck(observation['location'], observation['walls'], enemy['location']) == []:
            action = self.goToPoint(observation , enemy['location'], closest_distance)
            return action
        else:
            action = {
                       'turn': math.radians(self.angleWithAgent(toAttack['location'], observation['location'], observation['direction'])),
                       'speed': 0,
                       'shoot': True
                      }
                      
            if closest_distance <= settings.MAX_SHOT_DISTANCE:       
#                print "giving 100 reward for shooting when theres an enemy"
                self.extraReward += self.shootingReward
            else:
#                print "giving -100 reward for shooting when out of range"
                self.extraReward += self.outOfRange
                      
            return action
                
    def goToControlpoint(self,observation):
        controlpoints = observation['controlpoints']
        uncontrolled = []
        for controlpoint in controlpoints:
            if not self.isControlled(controlpoint, observation['team']):
                uncontrolled.append(controlpoint)
        if uncontrolled == []:
            uncontrolled = controlpoints
        closest_distance = 9999999999
        closest = []        
        for controlpoint in uncontrolled:
            distance = self.getDistance(observation['location'], controlpoint['location'])
            if distance < closest_distance:
                closest_distance = distance
                closest = controlpoint['location']
        action = self.goToPoint(observation, closest, closest_distance)
#        angle = self.angleWithAgent(closest['location'], observation['location'], observation['direction'])
#        obstacle = self.obstacleCheck(observation['location'], observation['walls'], closest['location']);
#        if not obstacle == []:
#            # Wall in the way
#            waypoint = self.getNearestWaypoint(observation['location'])
#            angle = self.angleWithAgent(waypoint, observation['location'], observation['direction'])
#        if angle >= -60 and angle <= 60:
#            speed = closest_distance
#        else:
#            speed = 0
#        action = {
#                   'turn': math.radians(angle),
#                   'speed': speed,
#                   'shoot': False
#                  }
        return action                
    
    def goToPoint(self, observation, point, distance):
        if not self.obstacleCheck(observation['location'], observation['walls'], point) == []:
            waypoint = self.getNearestWaypoint(observation['location'])
            angle = self.angleWithAgent(waypoint, observation['location'], observation['direction'])
        else:
            angle = self.angleWithAgent(point, observation['location'], observation['direction']) 
        if angle >= -60 and angle <= 60:
            speed = distance
        else:
            speed = 0
        action = {
                    'turn': math.radians(angle),
                    'speed': speed,
                    'shoot': False
                    }
        return action
    
    def getNearestWaypoint(self, location):
        dist = 9999
        target = None
        for wp in self.waypoints:
            tmp = self.getDistance(location, wp)
            if tmp < dist:
                dist = tmp
                target = wp
        return target            
    
    def obstacleCheck(self, loc, walls, controlpoint):
        for wall in walls:
            x1 = float(wall['left'])
            y1 = float(wall['top'])
            x2 = float(wall['right'])
            y2 = float(wall['bottom'])
            if controlpoint[0] < loc[0]:
                u1 = float(controlpoint[0])
                v1 = float(controlpoint[1])
                u2 = float(loc[0])
                v2 = float(loc[1])
            else:
                u2 = float(controlpoint[0])
                v2 = float(controlpoint[1])
                u1 = float(loc[0])
                v1 = float(loc[1])
            if x1 - x2 == 0:
                x1 = x1+0.0001
            if u1 - u2 == 0:
                u1 = u1+0.0001
            b1 = (y1 - y2) / (x1 - x2)
            a1 = y1 - (b1*x1)
            if u1 - u2 == 0:
                # Vertical line
                y = a1 + (b1 * u1)
                if y < y1 or y > y2:
                    return []
                else:
                    return wall
            b2 = (v1 - v2) / (u1 - u2)
            a2 = v1 - (b2*u1)
            if b1-b2 == 0:
                return []
            xi = -1* ((a1 - a2) / (b1-b2))
            yi = a1 + (b1*xi) 
            if (x1-xi)*(xi-x2)>=0 and (u1-xi)*(xi-u2)>=0 and (y1-yi)*(yi-y2)>=0 and (v1-yi)*(yi-v2)>=0:
                return wall
        return []
    
    def angleWithAgent(self, agentlocation, location, direction):
        direction = -direction
        rel_x = agentlocation[0]-location[0]
        rel_y = agentlocation[1]-location[1]
        rot_x = rel_x * math.cos(direction) - rel_y * math.sin(direction)
        rot_y = rel_x * math.sin(direction) + rel_y * math.cos(direction)
        angle = math.atan2(rot_y, rot_x)
        
#        print 'dir',math.degrees(direction)
#        print 'loc',location
#        print 'rel_loc',rel_x,rel_y
#        print 'rot_x',rot_x,rot_y
#        print 'angle',math.degrees(angle)
        
        return math.degrees(angle)
    
    def isEnemy(self, agent, team):
        if agent['team'] == team:
            return False
        return True
    
    def isControlled(self, controlpoint, team):
        if controlpoint['team'] == team:
            return True
        return False
    
    def saveDict(self,stateValuesDict,agentNr,team):
        fileName = 'brains/g6/stateValues.pickle'+str(agentNr)+team
        os.path.normcase(fileName)
        stateValuesFile = open(fileName, 'wb')          
        pickle.dump(stateValuesDict,stateValuesFile,-1)
        # close file
        stateValuesFile.close()
    
    def openDict(self,agentNr,team):
        fileName = 'brains/g6/stateValues.pickle'+str(agentNr)+team
        os.path.normcase(fileName)        
        stateActionFile = open(fileName, 'ab+')
        try:
            # try to open existing dictionary                               
            stateActionDict = pickle.load(stateActionFile)
        except:    
            # if it fails make a new empty one
#            print "couldnt unpickle dict"
#            print fileName
            stateActionDict = {}
        stateActionFile.close()       
        return stateActionDict
    
    def update(self, stateActionDict, observation, state):
        if self.previousState != '':
            alpha = 0.1
            gamma = 0.9
        
            if self.previousState in stateActionDict:
                actionValues = stateActionDict[self.previousState];
            else:
                actionValues = self.DEFAULTVALUES
        
            prevValue = actionValues[self.previousAction]
            reward = self.getReward(observation)
#            print "immediate reward: "
#            print reward
            maxValue = self.getMaxValue(stateActionDict[state])
            actionValues[self.previousAction] = prevValue + alpha * (reward + gamma * maxValue - prevValue)            
            stateActionDict[self.previousState] = actionValues
        return stateActionDict
#        stateValuesDict[previousState] = stateValuesDict[previousState] 
#            + self.alpha * (self.getReward(observation) + 
#                            self.gamma * MAX(stateValuesDict[state_string]) - 
#                            stateValuesDict[previousState])
    
    def getMaxValue(self, actionValues):
        toReturn = -999999
        for _action, value in actionValues.iteritems():
            if value > toReturn:
                toReturn = value
        return toReturn
    
    def getReward(self,observation):
        reward = 0      
        for controlpoint in observation['controlpoints']:
            if controlpoint['team'] == observation['team']:
                reward += 0
#            if controlpoint['team'] != observation['team'] and controlpoint['team'] != 'Neutral':
#                reward -= 1
        if observation['respawn'] == 1:
            reward += self.respawnReward
        reward += self.extraReward
        self.extraReward = 0
        return reward
        
    def toState(self, observation):
        # slices are ordered as: 
        #[ EnemyInSight, EnemyInRange, EnemyBehindAgent, AmmoInFront, 
        #  AmmoBehind, AgentHasAmmo, UncontrolledControlpoint, 
        #  AgentNearControlpoint]
        state = [0,0,0,0,0,0,0,0]
        
        location = observation['location']
        direction = observation['direction']
        agents = observation['agents']
        ammopacks = observation['ammopacks']
        controlpoints = observation['controlpoints']

        # check agents
        if agents != []:
            for agent in agents:
                if self.isEnemy(agent, observation['team']):
                    angle = self.angleWithAgent(agent['location'],location,direction)
                    if angle <= settings.MAX_TURN and angle >= -settings.MAX_TURN and self.getDistance(location, agent['location']) < settings.MAX_SHOT_DISTANCE:
                        state[1] = 1
                    elif angle <= 2*settings.MAX_TURN and angle >= 2* -settings.MAX_TURN and self.getDistance(location, agent['location']) < settings.SIGHT:
                        state[0] = 1
                    else:
                        state[2] = 1
        
        # check ammopacks
        if ammopacks != []:
            for ammopack in ammopacks:
                angle = self.angleWithAgent(ammopack['location'],location,direction)
                if angle <= settings.MAX_TURN and angle >= -settings.MAX_TURN:
                    state[3] = 1
                else:
                    state[4] = 1
                    
        # check ammo
        if(observation['ammo'] > 0):
            state[5] = 1
        
        # check controlpoints and if distance to closest controlpoint
        # is less then or equal to 25 pixels
        for controlpoint in controlpoints:
            minimal_distance = 25
            if not self.isControlled(controlpoint, observation['team']):
                state[6] = 1
            dist = self.getDistance(location, controlpoint['location'])
            if dist <= minimal_distance:
                state[7] = 1
                        
        # construct string
        state = ''.join(str(n) for n in state)
        return state
    
    def spawnKiller(self, observation):
        
        action = None
        agents = observation['agents']
        enemiesInSight = []
        distance = 0
        point = (0,0)
        debug = ''
        minDistance = 0
        
        # check distance to other team spawn point      
        if observation['team'] == 'Red':
            point = (35, 35)
            distance = self.getDistance(observation['location'], point)
        else:
            point = (965, 965)
            distance = self.getDistance(observation['location'], point)
            
        # Get enemy agents
        for agent in agents:
            if agent['team'] != observation['team']:
                if distance > 50:
                    angle = self.angleWithAgent(agent['location'], observation['location'], observation['direction'])
                    if angle >= -60 and angle <= 60:
                        enemiesInSight.append(agent)
                else:
                    enemiesInSight.append(agent)
        
        # If no enemies 
        if enemiesInSight == []:
            # and no ammopacks near and further than 50 pixels away, go to spawn point
            if observation['ammopacks'] == [] and distance > minDistance:
                action = self.goToPoint(observation, point, distance)
                debug = 'No ammopacks and  not close enough, move to spawn point'
            # No ammo but close enough
            elif observation['ammopacks'] == [] and distance <= minDistance:
                # Move between spawn and middle and 25% chance of random move
                if observation['ammo'] == 0:
                    distance= self.getDistance(observation['location'], (500, 500))
                    action = self.goToPoint(observation, (500, 500), distance )
                else:
                    action = self.goToPoint(observation, (500, 500), 0)
#                if random.random() <= 0.25:
#                    action = {
#                   'turn': math.radians(random.random()*math.pi/1.5 - math.pi/3),
#                   'speed': 50,
#                   'shoot': False
#                  }
#                    debug = 'No ammopacks, close enough and move random' 
#                else:
#                    action = {
#                   'turn': 0,
#                   'speed': 0,
#                   'shoot': False
#                  }
#                    distance = self.getDistance(observation['location'], (500, 500))
#                    debug = 'No ammopacks, close enough towards middle'
#                    action = self.goToPoint(observation, (500, 500), distance)
#                    if self.getDistance(observation['location'], (500, 500)) > 200:
#                        turn = self.angleWithAgent((500, 500), observation['location'], observation['direction'])
#                    else:
#                        turn = self.angleWithAgent(point, observation['location'], observation['direction'])
            # Ammopacks near and less than 10 ammo, get ammo
            elif observation['ammo'] <= 10:
                action = self.getAmmo(observation, True)
                debug = 'Ammopacks near, not enough ammo and getting ammo'
            # Ammo near but enough
            elif observation['ammo'] > 10:
                # Not close enough to spawn so move nearer
                if distance > minDistance:
                    action = self.goToPoint(observation, point, distance)
                    debug = 'Ammopacks near, enough ammo but not close enough, move towards spawn point'
                # Close enough, roam around randomly
                else:
                    debug = 'Ammopacks near, enough ammo and close enough, move random'
                    action = {
                              'turn': random.random()*math.pi/1.5 - math.pi/3,
                              'speed': 50,
                              'shoot': False
                              }
                
        # Enemies in sight
        else:
            # In possession of ammo
            if not observation['ammo'] == 0:
                closest_distance = settings.SIGHT*2
                toAttack = []
                for enemy in enemiesInSight:
                    distance2 = self.getDistance(observation['location'],enemy['location'])
                    if distance2 < closest_distance:
                        if self.obstacleCheck(observation['location'], observation['walls'], enemy['location']) == []:
                            closest_distance = distance2
                            toAttack = enemy
                if toAttack == []:
                    debug = 'Enemies near, have ammo but none to attack: move to spawn point'
                    action = self.goToPoint(observation, point, distance)
                # If close enough to enemy
                elif closest_distance <= settings.MAX_SHOT_DISTANCE:
                    angle = self.angleWithAgent(toAttack['location'], observation['location'], observation['direction'])
                    if angle >= -settings.MAX_TURN and angle <= settings.MAX_TURN:
                        debug = 'Enemies near, have ammo going to attack'
                        action = {
                                   'turn': math.radians(angle),
                                   'speed': 0,
                                   'shoot': True
                                  }
                    else:
                        debug = 'Enemies near, have ammo but not in radius, going to turn'
                        action = {
                                   'turn': math.radians(angle),
                                   'speed': 0,
                                   'shoot': False
                                  }
                        
                # Not close enough, move a little closer
                else:
                    debug = 'Enemies near, have ammo but not close enough, move and turn'
                    action = {
                               'turn': math.radians(self.angleWithAgent(toAttack['location'], observation['location'], observation['direction'])),
                               'speed': 50,
                               'shoot': False
                              }
            # No ammo
            else:
                # No ammopacks near
                if observation['ammopacks'] == []:
                    # Flee
                    debug = 'Enemies near but no ammo and none near, flee'
#                    action = self.flee(observation)
                    turn  = self.angleWithAgent((500, 500), observation['location'], observation['direction'])
                    action = {
                              'turn': math.radians(turn),#random.random()*math.pi/1.5 - math.pi/3,
                              'speed': 50,
                              'shoot': False
                              }
                else:
                    # Get ammo
                    debug = 'Enemies near but no ammo but ammo near, getting ammo'
                    action = self.getAmmo(observation, True)
#        if action['turn'] == 0 and action['speed'] == 0:
#            print observation
            
#        print debug
        return action